/*
 * =====================================================================================
 *
 *       Filename:  Vector.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  01/07/12 18:24:01
 *       Revision:  none
 *       Compiler:  g++
 *
 *         Author:  LittleQ Su (), 98703060@nccu.edu.tw
 *        Company:  National Chengchi University, The Department of Computer Science
 *
 * =====================================================================================
 */
#include "Vector.h"

// Constructors & desctructors
template <class T>
Vector<T>::Vector() {
    this -> _data = 0;
    this -> _avail = 0;
    this -> _limit = 0;

}

template <class T>
Vector<T>::Vector(int n_capacity) {
    this -> _data = _alloc.allocate(capacity);
    _limit = _avail = _data + n_capacity;
    uninitialized_fill(_data, _limit, NULL);
}

template <class T>
Vector<T>::Vector(const Vector& src) {
    iterator begin = src.begin();
    iterator end = src.end();

    _data = _alloc.allcate(end - begin);
    _limit = _avail = uninitialized_copy(begin, end, _data);
}

template <class T>
Vector<T>::~Vector() {
    this -> clear();
}

// Member functions
template <class T>
void Vector<T>::insert(int index, const T& target) {
    _check_index(index);
    if ( _avail == _limit ) {
        this -> _grow();
    }
    iterator insert_point = &(_data[index]);

    for ( iterator i = this -> end(); i > insert_point; --i) {
        *(i+1) = *i;
    }

    *insert_point = target;
}

template <class T>
void Vector<T>::erase(int index) {
    _check_index(index);
    iterator erase_point = &(_data[index]);
    iterator i;

    for ( i = erase_point; i < (_avail-1); --i) {
        *i = *(i+1);
    }

    _avail--;
    (*_avail) = NULL;
}

template <class T>
void Vector<T>::swap( Vector& target) {

}

template <class T>
void Vector<T>::clear() {
    if ( _data ) {
        iterator it = _avail;
        while ( it != _data ) {
            _alloc.destroy(--it);
        }

        _alloc.deallocate(_data, _limit - _data);
    }

    _data = _limit = _avail = 0;
}

template <class T>
int Vector<T>::size() const {
    return (int)(_avail - _data);
}

template <class T>
int Vector<T>::capacity() const {
    return (int)(_limit - _data);
}

template <class T>
typename Vector<T>::iterator Vector<T>::begin() const {
    return _data;
}

template <class T>
typename Vector<T>::iterator Vector<T>::end() const {
    return _avail;
}
template <class T>
T& Vector<T>::operator[] (int i) {
    _check_index(i);
    return _data[i];
}

template <class T>
const T& Vector<T>::operator[] (int i) const {
    _check_index(i);
    return _data[i];
}
// Private

template <class T>
void Vector<T>::_grow() {
    size_type new_size = max( 2 * (_limit - _data), ptrdiff_t(1));

    iterator new_data = _alloc.allocate(new_size);
    iterator new_avail = uninitialized_copy(_data, _avail, new_data);

    this -> clear();

    _data = new_data;
    _avail = new_avail;
    _limit = _data + new_size;
}

template <class T>
void Vector<T>::_check_index(int index) const {
    if ( !(index > 0 && index < (_avail-_data) ))
        throw (Exception("Array index out of bounds"));
}
